package cn.changeforyou.cmd.generator.db.mybatisplus;

import cn.changeforyou.analyzer.ParseException;
import cn.changeforyou.analyzer.combine.orm.compare.EntityAndTableComparetor;
import cn.changeforyou.analyzer.combine.orm.compare.EntityAndTableComparetor.EntityAndTableCompareResult;
import cn.changeforyou.analyzer.combine.orm.compare.EntityAndXmlComparator;
import cn.changeforyou.analyzer.combine.orm.compare.EntityAndXmlComparator.XmlCompareResult;
import cn.changeforyou.analyzer.combine.orm.compare.compareResultProcessor.InsertAndDeleteFieldEntityCompareResultProcessor;
import cn.changeforyou.analyzer.configFileParse.SpringBootConfigUtils;
import cn.changeforyou.analyzer.configFileParse.model.MysqlConfig;
import cn.changeforyou.analyzer.dbParse.DatabaseUtil;
import cn.changeforyou.analyzer.dbParse.mybatisPlusGenerator.MybatisPlusGeneratorUtils;
import cn.changeforyou.analyzer.dbParse.model.MysqlTableInfo;
import cn.changeforyou.analyzer.javaparse.JavaParseUtils;
import cn.changeforyou.analyzer.javaparse.model.EntityModel;
import cn.changeforyou.analyzer.xmlparse.mybatis.MybatisXmlParse;
import cn.changeforyou.analyzer.xmlparse.mybatis.model.MybatisXmlContent;
import cn.changeforyou.cmd.generator.CmdGenerator;
import cn.changeforyou.cmd.generator.CmdGeneratorParameter;
import cn.changeforyou.cmd.generator.ConstantVar;
import cn.changeforyou.cmd.generator.GeneratorContext;
import cn.changeforyou.cmd.generator.db.mybatisplus.parameters.EntityAndXmlGeneratorParameters;

import com.baomidou.mybatisplus.generator.config.po.TableInfo;

import java.util.List;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;


/**
 * @author zhyu
 * @date 2021/2/4 12:06
 */
public class EntityAndXmlGenerator implements CmdGenerator {
	
	public static void main(String[] args) {
		new EntityAndXmlGenerator().start();
	}
	
	@Override
	public String getSign() {
		return "entityAndXml";
	}
	
	@Override
	public boolean generate_do(GeneratorContext context, CmdGeneratorParameter params) {
		//获取系统的数据库参数 yml读取配置文件,指定返回类型为Map,Map中value类型为LinkedHashMap
		EntityAndXmlGeneratorParameters entityAndXmlGeneratorParameters = (EntityAndXmlGeneratorParameters) params;
		@NotEmpty String entityName = entityAndXmlGeneratorParameters.getEntityName();
		@NotEmpty String projectPath = entityAndXmlGeneratorParameters.getProjectPath();
		MysqlConfig mysqlConfig = SpringBootConfigUtils.getMysqlConfigFromSpringBootProject(projectPath);
		if (null == mysqlConfig) {
			System.out.println("springboot 项目中配置db的文件没找到, 请先检查配置");
			return false;
		} else {
			System.out.println("解析到数据库配置: " + mysqlConfig);
		}
		
		//获取实体类信息
		EntityModel entityModel = JavaParseUtils.getMybatisPlusEntityModelFromEntityNameAndProjectPath(entityName, projectPath);
		if (log.isDebugEnabled()) {
			log.debug("实体类解析结果\n {}", entityModel);
		}
		if (null == entityModel) {
			throw new RuntimeException("实体类不存在");
		}
		
		//获取mysql信息
		DatabaseUtil databaseUtil = new DatabaseUtil(mysqlConfig.getUrl(), mysqlConfig.getUsername(), mysqlConfig.getPassword());
		MysqlTableInfo mysqlTableInfo = databaseUtil.getMysqlTableInfo(entityModel.getTableName());
        if (log.isDebugEnabled()) {
            log.debug("mysql表解析结果\n {}", entityModel);
        }
		
		//利用mybatisPlus generator获取信息
		MybatisPlusGeneratorUtils mybatisPlusGeneratorUtils = new MybatisPlusGeneratorUtils(databaseUtil);
		List<TableInfo> tablesInfo = mybatisPlusGeneratorUtils.getTablesInfo(entityModel.getTableName());
		context.putInKeyMap(ConstantVar.TABLE_INFO, tablesInfo);
        if (log.isDebugEnabled()) {
            log.debug("mybatisPlus generator 解析结果\n {}", tablesInfo);
        }
		
		EntityAndTableComparetor entityAndTableComparetor = new EntityAndTableComparetor();
		@NotNull EntityAndTableCompareResult compareResult = entityAndTableComparetor.compare(mysqlTableInfo, entityModel);
		log.debug("比较结果: {}", compareResult);
		if (!compareResult.isEmpty()) {
			log.info("实体类和mysql表有差异, 开始进行结果处理");
			context.putInClassMap(compareResult);
			context.putInKeyMap(ConstantVar.PROJECT_KEY, projectPath);
			context.putInKeyMap(ConstantVar.ENTITY_NAME_KEY, entityName);
			InsertAndDeleteFieldEntityCompareResultProcessor processor = new InsertAndDeleteFieldEntityCompareResultProcessor();
            boolean start = processor.start();
            if(!start) {
                log.error("实体类的修改或新增失败, 程序结束");
                throw new ParseException();
            }
            
            //更新mysqlInfo 和 实体类信息
            entityModel = JavaParseUtils.getMybatisPlusEntityModelFromEntityNameAndProjectPath(entityName, projectPath);
   
		} else {
			log.info("实体类和mysql表一致, 不用进行处理");
		}
		
		//解析 xml
		MybatisXmlContent mybatisXmlContent = new MybatisXmlParse(mysqlTableInfo.getTableName()).getMybatisXmlEntity(entityAndXmlGeneratorParameters.getXmlPath());
        if (log.isDebugEnabled()) {
            log.debug("解析xml, \n{}", mybatisXmlContent);
        }
        
        //比较xml和实体类
		EntityAndXmlComparator entityAndXmlComparator = new EntityAndXmlComparator();
		XmlCompareResult xmlCompareResult = entityAndXmlComparator.compare(mybatisXmlContent, entityModel);
		if (log.isInfoEnabled()) {
			log.info("比较出xml标签和实体的结果\n {}", xmlCompareResult);

		}
		if (!xmlCompareResult.isOk()) {
			log.info("发现xml标签和实体的结果不一致, 现在开始处理");
			XmlCompareResultExecutor xmlExecutor = new XmlCompareResultExecutor();
			xmlExecutor.execute(xmlCompareResult, mybatisXmlContent, context);
		}
		
		
		return true;
	}
	
	
	@Override
	public String getName() {
		return "mybatis-plus 实体类xml生成校对器";
	}
	
	@Override
	public Class getParameterClass() {
		return EntityAndXmlGeneratorParameters.class;
	}
	
	@Override
	public void init(GeneratorContext context) {
	
	}
	
}
